import subprocess
import resource
import time
import sys
import psutil
import json

# Start comparison
def doCompare(comparer, inputFile, outputFile, ansFile):
    if comparer is 'default' or comparer is '':
        return comparerDefault(outputFile, ansFile)
    else:
        diff = subprocess.Popen('{0} {1} {2} {3}'.format(comparer, inputFile, outputFile, ansFile), shell=True, stdout=subprocess.PIPE)
        diff.wait()
        if diff.returncode:
            message = diff.stdout.read()
            if type(message) is bytes:
                message = message.decode('UTF-8')
            return (2, message)
        else:
            return (1, '')

# Default comparer
def comparerDefault(outputFile, ansFile):
    diff = subprocess.Popen('diff {0} {1} --ignore-tab-expansion --ignore-trailing-space --ignore-blank-lines --width=20'.format(outputFile, ansFile), shell=True, stdout=subprocess.PIPE)
    diff.wait()
    if diff.returncode:
        message = diff.stdout.read()
        if type(message) is bytes:
            message = message.decode('UTF-8')
        return (2, message)
    else:
        return (1, '')

# Main function
def main(argv):
    # Config
    program, inputFile, ansFile = argv[1], argv[2], argv[3]
    timeout, memoryLimit = int(argv[4]) / 1000, int(argv[5]) * 1000
    comparer = argv[6]
    status, message = None, ''
    startTime = endTime = 0

    # Execute program
    with open(inputFile, 'r') as input, open('/tmp/exec/output', 'w') as output:
        process = subprocess.Popen(program, shell=False, stdin=input, stdout=output)
        startTime = time.time()
        while process.poll() is None:
            proc = psutil.Process(process.pid)
            endTime = time.time()
            if endTime - startTime > timeout:
                process.kill()
                status = 5
                break
            elif proc.memory_info().rss > memoryLimit:
                process.kill()
                status = 6
                break

    # Check runtime error
    if status is None:
        if process.returncode is not 0:
            status = 3
        else:
            status, message = doCompare(comparer, inputFile, '/tmp/exec/output', ansFile)

    # Get info
    info = resource.getrusage(resource.RUSAGE_CHILDREN)

    # Return result
    result = {'status':status, 'info':message, 'time':int((endTime-startTime)*1000), 'memory':info.ru_maxrss}
    return result

# Call main()
if __name__ == '__main__':
    print(main(sys.argv))